# TriggerSwitchD, executes commands to activate/deactive remote switches.
# (c) Copyright 2010 Pontus Strömdahl, AdhocSkill. 
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


require File.join(File.dirname(__FILE__),"protocol_loader")
require File.join(File.dirname(__FILE__),"..","code_converter")

module Tellstick
  module Proove #:nodoc:
    include ProtocolLoader
    def turn_on(*args)
      args << true
      output.puts build_command_string(*Proove::preprocess_build_command_args(*args))
    end

    def turn_off(*args)
      args << false
      output.puts build_command_string(*Proove::preprocess_build_command_args(*args))
    end

    def teach(*args)
      args += [true,2]
      (1..5).each do
        @output.puts build_command_string(*Proove::preprocess_build_command_args(*args))
        @output.gets
        sleep 0.2
      end
    end

    def output
      @output
    end
    
    private
    
    attr_reader :convert_it
    def convert_it
      @convert_it ||= CodeConverter.new([/\d+/,/[A-D]/,/[a-d]/])
    end
    
    def self.part_for(code,number_of_bits)
      result = ""
      (0..number_of_bits).each do |index|
        result << (((code & 1) << (number_of_bits - index) == 1)? "10" : "01")
      end
      result
    end
    
    def self.character_bit_pattern(code,character)
      code <<= 4
      return (code | 8) if character == "1"
      (code | 10)  
    end
    
    def self.translate(code_part)
    	code = 9
    	translate_inner(code_part) do |result, character,index|
        code = code_tmp = character_bit_pattern(code,character)
        code = 0 if (index % 2 == 0)
        translate_update_result(result,code_tmp,index)
      end
    end
    
    def self.translate_update_result(result,code,index)
      return result if (index % 2 != 0)
      result << code.chr
    end
        
    def self.translate_inner(code_part)
      index = 0
    	code_part.scan(/./).inject("") do |result, character|
    	  result = yield(result, character, index)
    	  index += 1
    	  result
      end
    end
    
    def self.signal_part(house_code, unit,on_off)
      unit_code = unit.to_i - 1
      Proove::translate("#{part_for(house_code,25)}01#{on_off}#{part_for(unit_code,3)}0")
    end
    
    def self.preprocess_build_command_args(*args)
      args << 5 if args.length < 4
      args
    end
    
    def build_command_string(*args)
      house,unit,on,number_repeat = args
      house_code = convert_it.to_i(house) 
      on_off = on ? "10" : "01"
      "R#{number_repeat.chr}T\177\377\030\001\204#{Proove::signal_part(house_code,unit,on_off)}+"
    end    
  end
end